package com.dashu.core.service;

import com.dashu.base.enums.BusinessType;
import com.dashu.base.enums.ReplRyCode;
import com.dashu.base.enums.common.CompanyType;
import com.dashu.base.enums.school.SchoolType;
import com.dashu.base.utils.CopyUtil;
import com.dashu.base.utils.UIDUtil;
import com.dashu.base.utils.VerificationUtil;
import com.dashu.core.dto.UserDTO;
import com.dashu.core.dto.company.CompanyDTO;
import com.dashu.core.handler.VerificationException;
import com.dashu.core.model.Company;
import com.dashu.core.model.CompanyDepartment;
import com.dashu.core.model.QCompany;
import com.dashu.core.result.PageEnty;
import com.dashu.core.vo.RelationshipCompanyVO;
import com.dashu.core.vo.UpdateEntityVO;
import com.dashu.core.vo.company.CompanyListVO;
import com.dashu.core.vo.company.CompanyVO;
import com.dashu.core.vo.company.UpCompanyVO;
import com.querydsl.core.BooleanBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.persistence.FlushModeType;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class CompanyService extends DataService {
    @Autowired
    private UserService userService;
    @Autowired
    private CompanyDepartmentService companyDepartmentService;
    @Autowired
    private CompanyTeacherService companyTeacherService;
    @Autowired
    private CompanyParentService companyParentService;
    @Autowired
    private AttendanceTimeService attendanceTimeService;

    @Transactional
    public CompanyDTO add(CompanyVO companyVO) {
        Company company = CopyUtil.copyEnty(companyVO, Company.class);
        try {
            long userId = Long.parseLong(VerificationUtil.getUserId());
            company.setId(UIDUtil.nextId());
            company.setCreateUser(userId);
            company.setCreateTime(System.currentTimeMillis());
            company.setBaseId(userId);
            entityManager.persist(company);
//            entityManager.flush();
            entityManager.setFlushMode(FlushModeType.AUTO);
            attendanceTimeService.addDefult(company.getId());
        } catch (Exception e) {
            e.printStackTrace();
            throw new VerificationException(ReplRyCode.DATA_NOT_INVALID, ReplRyCode.DATA_NOT_INVALID.getMessage());
        }
        CompanyDTO companyDTO = CopyUtil.copyEnty(company, CompanyDTO.class);
        return companyDTO;

    }

    @Transactional
    public boolean deleteByCompanyId(long companyId) throws Exception {
        QCompany qCompany = QCompany.company;
        List<CompanyDepartment> companyDepartments = companyDepartmentService.findByCompanyId(companyId);
        if (companyDepartments.size() > 0)
            throw new VerificationException(ReplRyCode.EXIST_GL_DEPARTMENT, ReplRyCode.EXIST_GL_DEPARTMENT.getMessage());
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompany.id.eq(companyId));
        Company company = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder.getValue())
                .fetchOne();
        if (company == null) {
            throw new VerificationException(ReplRyCode.COMPANY_NOT_DATA, ReplRyCode.COMPANY_NOT_DATA.getMessage());
        }
        companyTeacherService.deleteCompany(companyId);
        companyParentService.deleteCompany(companyId);
        entityManager.remove(company);
//            entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);
        return true;
    }

    @Transactional
    public CompanyDTO updataByCompanyId(UpdateEntityVO<UpCompanyVO> updateCompanyVO) throws Exception {
        QCompany qCompany = QCompany.company;
        long userId = Long.parseLong(VerificationUtil.getUserId());
        UpCompanyVO upCompanyVO = updateCompanyVO.getEntityVO();
        CompanyDTO companyDTO = existByCompanyName(upCompanyVO.getCompanyName(), updateCompanyVO.getId());
        if (companyDTO != null) {
            throw new VerificationException(ReplRyCode.EXIST_COMPANY, ReplRyCode.EXIST_COMPANY.getMessage());
        }
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompany.id.eq(updateCompanyVO.getId()));
        Company company;
        company = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder.getValue()).fetchOne();
        if (company == null)
            throw new VerificationException(ReplRyCode.COMPANY_NOT_DATA, ReplRyCode.COMPANY_NOT_DATA.getMessage());
        company.setUpdateUser(userId);
        company.setUpdateTime(new Date().getTime());
        if (upCompanyVO.getAddress() != null)
            company.setAddress(upCompanyVO.getAddress());
        if (upCompanyVO.getBusinessType() != null)
            company.setBusinessType(BusinessType.map.get(upCompanyVO.getBusinessType()));
        if (upCompanyVO.getCompanyName() != null)
            company.setCompanyName(upCompanyVO.getCompanyName());
        if (upCompanyVO.getCompanyType() != null)
            company.setCompanyType(CompanyType.map.get(upCompanyVO.getCompanyType()));
        if (upCompanyVO.getSchoolType() != null)
            company.setSchoolType(SchoolType.map.get(upCompanyVO.getSchoolType()));
        if (upCompanyVO.getX() != null)
            company.setX(upCompanyVO.getX());
        if (upCompanyVO.getY() != null)
            company.setY(upCompanyVO.getY());
        if (upCompanyVO.getCity() != null)
            company.setCity(upCompanyVO.getCity());
        if (upCompanyVO.getProvince() != null)
            company.setProvince(upCompanyVO.getProvince());
        company = entityManager.merge(company);
//        entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);
        CompanyDTO copDTO = CopyUtil.copyEnty(company, CompanyDTO.class);
        return copDTO;

    }


    @Transactional
    public boolean deleteRelation(long companyId) throws Exception {
        QCompany qCompany = QCompany.company;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompany.id.eq(companyId));
        Company company = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder.getValue()).fetchOne();
        if (company == null)
            throw new VerificationException(ReplRyCode.COMPANY_NOT_DATA, ReplRyCode.COMPANY_NOT_DATA.getMessage());
        UserDTO userDTO = userService.findByUserId(company.getBaseId());
        company.setUpdateUser(company.getBaseId());
        company.setUpdateTime(new Date().getTime());
        company.setBaseId(userDTO.getBaseId());
        entityManager.merge(company);
//        entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);
//        CompanyDTO CompanyDTO = CopyUtil.copyEnty(company, CompanyDTO.class);
        return true;

    }

    @Transactional
    public boolean creteRelation(RelationshipCompanyVO relationshipCompanyVO) throws Exception {
        QCompany qCompany = QCompany.company;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        long userId = Long.parseLong(VerificationUtil.getUserId());
        booleanBuilder.and(qCompany.id.in(relationshipCompanyVO.getCompanyId()));
        List<Company> companys = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder.getValue())
                .fetch();
        if (companys == null)
            throw new VerificationException(ReplRyCode.COMPANY_NOT_DATA, ReplRyCode.COMPANY_NOT_DATA.getMessage());
        companys.stream().forEach(c -> {
            c.setUpdateUser(userId);
            c.setUpdateTime(new Date().getTime());
            c.setBaseId(relationshipCompanyVO.getUserId());
            entityManager.merge(c);
//        entityManager.flush();
            entityManager.setFlushMode(FlushModeType.AUTO);
        });
//        CompanyDTO CompanyDTO = CopyUtil.copyEnty(company, CompanyDTO.class);
        return true;

    }


    public List<CompanyDTO> findByCreteUser(PageEnty<Long> baseVo) {
        QCompany qCompany = QCompany.company;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompany.createUser.eq(baseVo.getBaseId()));
        List<Company> companys = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder.getValue())
                .fetch();
        List<CompanyDTO> recycleDTOS = CopyUtil.copyList(companys, CompanyDTO.class);
        return recycleDTOS;
    }

    public List<Company> findByBaseId(long baseId) {
        QCompany qCompany = QCompany.company;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        if (admin != baseId)
            booleanBuilder.and(qCompany.baseId.eq(baseId));
        List<Company> companys = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder.getValue())
                .fetch();
        return companys;
    }

    public CompanyDTO findByCompanyId(long companyId) {
        QCompany qCompany = QCompany.company;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompany.id.eq(companyId));
        Company company = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder.getValue()).fetchOne();
        if (company == null)
            throw new VerificationException(ReplRyCode.COMPANY_NOT_DATA, ReplRyCode.COMPANY_NOT_DATA.getMessage());
        CompanyDTO companyDTO = CopyUtil.copyEnty(company, CompanyDTO.class);
        return companyDTO;

    }


    public List<CompanyDTO> findByCompanyName(String companyName, long baseId) {
        QCompany qCompany = QCompany.company;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        if (admin != baseId)
            booleanBuilder.and(qCompany.baseId.eq(baseId));
        booleanBuilder.and(qCompany.companyName.like("%" + companyName + "%"));
        List<Company> companys = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder.getValue()).fetch();
        if (companys == null)
            throw new VerificationException(ReplRyCode.COMPANY_NOT_DATA, ReplRyCode.COMPANY_NOT_DATA.getMessage());
        List<CompanyDTO> companyDTOS = CopyUtil.copyList(companys, CompanyDTO.class);
        return companyDTOS;

    }

    public CompanyDTO existByCompanyName(String companyName, long companyId) {
        QCompany qCompany = QCompany.company;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompany.companyName.eq(companyName));
        if (companyId != 0)
            booleanBuilder.and(qCompany.id.notIn(companyId));
        Company company = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder.getValue()).fetchOne();
        CompanyDTO CompanyDTO = CopyUtil.copyEnty(company, CompanyDTO.class);
        return CompanyDTO;

    }

    public void isAdd(CompanyVO companyVO) {
        QCompany qCompany = QCompany.company;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompany.companyNum.eq(companyVO.getCompanyNum()));
        Company company = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder.getValue()).fetchOne();
        if (company != null)
            throw new VerificationException(ReplRyCode.EXIST_COMPANY_NUM, ReplRyCode.EXIST_COMPANY_NUM.getMessage());
        BooleanBuilder booleanBuilder1 = new BooleanBuilder();
        booleanBuilder1.and(qCompany.city.eq(companyVO.getCity()));
        booleanBuilder1.and(qCompany.province.eq(companyVO.getProvince()));
        booleanBuilder1.and(qCompany.address.eq(companyVO.getAddress()));
        Company company1 = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder1.getValue()).fetchOne();
        if (company1 != null)
            throw new VerificationException(ReplRyCode.EXIST_COMPANY_ADDRESS, ReplRyCode.EXIST_COMPANY_ADDRESS.getMessage());
    }


    public long companyCount(PageEnty<CompanyListVO> companyPageEntyVO) throws Exception {
        QCompany qCompany = QCompany.company;
        long userId = Long.parseLong(VerificationUtil.getUserId());
        if (companyPageEntyVO.getVo() == null)
            throw new VerificationException(ReplRyCode.DATA_ERROR, ReplRyCode.DATA_ERROR.getMessage());
        CompanyListVO companyListVO = companyPageEntyVO.getVo();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        long baseId = companyPageEntyVO.getBaseId() == 0 ? userId : companyPageEntyVO.getBaseId();
        if (admin != baseId) {
            booleanBuilder.and(qCompany.baseId.eq(baseId));
        }
        if (!StringUtils.isEmpty(companyListVO.getSchoolType()))
            booleanBuilder.and(qCompany.schoolType.eq(SchoolType.map.get(companyListVO.getSchoolType())));
        if (!StringUtils.isEmpty(companyListVO.getBusinessType()))
            booleanBuilder.and(qCompany.businessType.eq(BusinessType.map.get(companyListVO.getBusinessType())));
        if (!StringUtils.isEmpty(companyListVO.getCompanyName()))
            booleanBuilder.and(qCompany.companyName.eq(companyListVO.getCompanyName()));
        long count = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder.getValue())
                .fetchCount();
        return count;
    }

    public List<CompanyDTO> pageCompanyList(PageEnty<CompanyListVO> companyPageEntyVO) throws Exception {
        QCompany qCompany = QCompany.company;
        long userId = Long.parseLong(VerificationUtil.getUserId());
        if (companyPageEntyVO.getVo() == null)
            throw new VerificationException(ReplRyCode.DATA_ERROR, ReplRyCode.DATA_ERROR.getMessage());
        CompanyListVO companyListVO = companyPageEntyVO.getVo();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        long baseId = companyPageEntyVO.getBaseId() == 0 ? userId : companyPageEntyVO.getBaseId();
        if (admin != baseId) {
            booleanBuilder.and(qCompany.baseId.eq(baseId));
        }
        if (!StringUtils.isEmpty(companyListVO.getSchoolType()))
            booleanBuilder.and(qCompany.schoolType.eq(SchoolType.map.get(companyListVO.getSchoolType())));
        if (!StringUtils.isEmpty(companyListVO.getBusinessType()))
            booleanBuilder.and(qCompany.businessType.eq(BusinessType.map.get(companyListVO.getBusinessType())));
        if (!StringUtils.isEmpty(companyListVO.getCompanyName()))
            booleanBuilder.and(qCompany.companyName.like("%" + companyListVO.getCompanyName() + "%"));

        List<Company> company = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder.getValue())
                .offset((companyPageEntyVO.getPage() - 1) * companyPageEntyVO.getNum())
                .limit(companyPageEntyVO.getNum())
                .orderBy(qCompany.createTime.desc())
                .fetch();
        if (company == null)
            throw new VerificationException(ReplRyCode.COMPANY_NOT_DATA, ReplRyCode.COMPANY_NOT_DATA.getMessage());
        List<CompanyDTO> companyDTOS = CopyUtil.copyList(company, CompanyDTO.class);
        return companyDTOS;

    }


    public List<Company> creteUserAll(List<Long>  creteUsers) {
        QCompany qCompany = QCompany.company;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompany.createUser.in(creteUsers));
        List<Company> companys = queryFactory
                .select(qCompany)
                .from(qCompany)
                .where(booleanBuilder.getValue())
                .fetch();
        return companys;

    }

}
